package net.sudot.chess.plugin.payment.wechatpublic;

import net.sudot.chess.business.model.PaymentTransaction;
import net.sudot.chess.business.model.PluginConfig;
import net.sudot.chess.plugin.PluginAttributeConfig;
import net.sudot.chess.plugin.payment.PaymentPlugin;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * 微信支付(公众号支付)
 *
 * @author tangjialin on 2018-03-18.
 */
//@Component
public class WechatPublicPaymentPlugin extends PaymentPlugin {
    /** code请求URL */
    private static final String CODE_REQUEST_URL = "https://open.weixin.qq.com/connect/oauth2/authorize#wechat_redirect";
    /** openId请求URL */
    private static final String OPEN_ID_REQUEST_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
    /** prepay_id请求URL */
    private static final String PREPAY_ID_REQUEST_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    /** 查询订单请求URL */
    private static final String ORDER_QUERY_REQUEST_URL = "https://api.mch.weixin.qq.com/pay/orderquery";
    /** 扩展属性配置 */
    private List<PluginAttributeConfig> attributeConfigs = new ArrayList<>();

    {
        attributeConfigs.add(new PluginAttributeConfig("appId", "APP ID", true));
        attributeConfigs.add(new PluginAttributeConfig("appSecret", "通信密钥", true));
        attributeConfigs.add(new PluginAttributeConfig("mchId", "商户ID"));
        attributeConfigs.add(new PluginAttributeConfig("apiKey", "API KEY"));
        attributeConfigs.add(new PluginAttributeConfig(PaymentPlugin.LOGO_ATTRIBUTE_NAME, "LOGO"));
        attributeConfigs.add(new PluginAttributeConfig(PaymentPlugin.DESCRIPTION_ATTRIBUTE_NAME, "描述"));
    }

    @Override
    public String getName() {
        return "微信支付(公众号支付)";
    }

    @Override
    public List<PluginAttributeConfig> getAttributeConfigs() {
        return attributeConfigs;
    }

    @Override
    public boolean supports(HttpServletRequest request) {
        return true;
//        String userAgent = request.getHeader("USER-AGENT");
//        return StringUtils.contains(userAgent.toLowerCase(), "micromessenger");
    }

    @Override
    public String payBeforeHandle(PaymentTransaction paymentTransaction, String paymentDescription, String extra, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> parameterMap = new HashMap<>();
        parameterMap.put("appid", getAppId());
        parameterMap.put("redirect_uri", getPayUrl(paymentTransaction.getSn(), extra));
        parameterMap.put("response_type", "code");
        parameterMap.put("scope", "snsapi_base");

//        request.setAttribute("requestUrl", CODE_REQUEST_URL);
        request.setAttribute("requestUrl", "/payment/mock");
        request.setAttribute("parameterMap", parameterMap);
        return super.payBeforeHandle(paymentTransaction, paymentDescription, extra, request, response);
    }

    @Override
    public String payHandle(PaymentTransaction paymentTransaction, String paymentDescription, String extra, HttpServletRequest request, HttpServletResponse response) {
//        String code = request.getParameter("code");
//        if (StringUtils.isEmpty(code)) {
//            return "/error/400";
//        }
//
//        String openId = getOpenId(code);
//
//        TreeMap<String, Object> parameterMap = new TreeMap<>();
//        parameterMap.put("appid", getAppId());
//        parameterMap.put("mch_id", getMchId());
//        parameterMap.put("nonce_str", DigestUtils.md5Hex(UUID.randomUUID() + RandomStringUtils.randomAlphabetic(30)));
//        parameterMap.put("body", StringUtils.abbreviate(paymentDescription.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5 ]", ""), 600));
//        parameterMap.put("out_trade_no", paymentTransaction.getSn());
//        parameterMap.put("total_fee", paymentTransaction.getAmount().multiply(new BigDecimal(100)).setScale(0).toString());
//        parameterMap.put("spbill_create_ip", request.getLocalAddr());
//        parameterMap.put("notify_url", getPayAfterUrl(paymentTransaction.getSn(), extra));
//        parameterMap.put("trade_type", "JSAPI");
//        parameterMap.put("openid", openId);
//        parameterMap.put("sign", generateSign(parameterMap));
//
//        String result = WebUtils.post(PREPAY_ID_REQUEST_URL, XmlUtils.toXml(parameterMap));
//        Map<String, String> resultMap = XmlUtils.toObject(result, new TypeReference<Map<String, String>>() {
//        });
//
//        String prepayId = resultMap.get("prepay_id");
//        String tradeType = resultMap.get("trade_type");
//        String resultCode = resultMap.get("result_code");
//
//        if (StringUtils.equals(tradeType, "JSAPI") && StringUtils.equals(resultCode, "SUCCESS")) {
//            parameterMap = new TreeMap<>();
//            parameterMap.put("appId", getAppId());
//            parameterMap.put("timeStamp", System.currentTimeMillis());
//            parameterMap.put("nonceStr", DigestUtils.md5Hex(UUID.randomUUID().toString()));
//            parameterMap.put("package", "prepay_id=" + prepayId);
//            parameterMap.put("signType", "MD5");
//            parameterMap.put("paySign", generateSign(parameterMap));
//        }
//        request.setAttribute("parameterMap", parameterMap);
        request.setAttribute("payAfterUrl", getPayAfterUrl(paymentTransaction.getSn(), extra));
        super.payHandle(paymentTransaction, paymentDescription, extra, request, response);
        return "net/sudot/chess/plugin/payment/wechatpublic/pay";
    }

    @Override
    public String payAfterHandle(PaymentTransaction paymentTransaction, String paymentDescription, String extra, boolean isPaySuccess, HttpServletRequest request, HttpServletResponse response) {
//		String xml = IOUtils.toString(request.getInputStream(), "UTF-8");
//		if (StringUtils.isEmpty(xml)) {
//			return;
//		}
//		Map<String, String> resultMap = XmlUtils.toObject(xml, new TypeReference<Map<String, String>>() {
//		});
//
//		if (StringUtils.equals(resultMap.get("return_code"), "SUCCESS")) {
//        request.setAttribute("message", "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
//		}
        return super.payAfterHandle(paymentTransaction, paymentDescription, extra, isPaySuccess, request, response);
    }

    @Override
    public boolean isPaySuccess(PaymentTransaction paymentTransaction, String paymentDescription, String extra, HttpServletRequest request, HttpServletResponse response) {
//		Map<String, Object> parameterMap = new TreeMap<>();
//		parameterMap.put("appid", getAppId());
//		parameterMap.put("mch_id", getMchId());
//		parameterMap.put("out_trade_no", paymentSn);
//		parameterMap.put("nonce_str", DigestUtils.md5Hex(UUID.randomUUID() + RandomStringUtils.randomAlphabetic(30)));
//		parameterMap.put("sign", generateSign(parameterMap));
//		String result = WebUtils.post(ORDER_QUERY_REQUEST_URL, XmlUtils.toXml(parameterMap));
//		Map<String, String> resultMap = XmlUtils.toObject(result, new TypeReference<Map<String, String>>() {
//		});
//		return StringUtils.equals(resultMap.get("return_code"), "SUCCESS") && StringUtils.equals(resultMap.get("result_code"), "SUCCESS") && StringUtils.equals(resultMap.get("trade_state"), "SUCCESS")
//				&& paymentTransaction.getAmount().multiply(new BigDecimal(100)).compareTo(new BigDecimal(resultMap.get("total_fee"))) == 0;
        return true;
    }

    /**
     * 获取AppID
     *
     * @return AppID
     */
    private String getAppId() {
        PluginConfig pluginConfig = getConfig();
        return pluginConfig.getAttribute("appId");
    }

    /**
     * 获取AppSecret
     *
     * @return AppSecret
     */
    private String getAppSecret() {
        PluginConfig pluginConfig = getConfig();
        return pluginConfig.getAttribute("appSecret");
    }

    /**
     * 获取商户号
     *
     * @return 商户号
     */
    private String getMchId() {
        PluginConfig pluginConfig = getConfig();
        return pluginConfig.getAttribute("mchId");
    }

    /**
     * 获取API密钥
     *
     * @return API密钥
     */
    private String getApiKey() {
        PluginConfig pluginConfig = getConfig();
        return pluginConfig.getAttribute("apiKey");
    }

//	/**
//	 * 获取OpenID
//	 *
//	 * @param code
//	 *            code值
//	 * @return OpenID
//	 */
//	private String getOpenId(String code) {
//		try {
//			OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
//			TokenRequestBuilder tokenRequestBuilder = OAuthClientRequest.tokenLocation(OPEN_ID_REQUEST_URL);
//			tokenRequestBuilder.setParameter("appid", getAppId());
//			tokenRequestBuilder.setParameter("secret", getAppSecret());
//			tokenRequestBuilder.setCode(code);
//			tokenRequestBuilder.setGrantType(GrantType.AUTHORIZATION_CODE);
//			OAuthClientRequest accessTokenRequest = tokenRequestBuilder.buildQueryMessage();
//			OAuthJSONAccessTokenResponse authJSONAccessTokenResponse = oAuthClient.accessToken(accessTokenRequest, OAuth.HttpMethod.GET);
//			return authJSONAccessTokenResponse.getParam("openid");
//		} catch (OAuthSystemException e) {
//			throw new BusinessException(e.getMessage(), e);
//		} catch (OAuthProblemException e) {
//			throw new BusinessException(e.getMessage(), e);
//		}
//	}

    /**
     * 生成签名
     *
     * @param parameterMap 参数
     * @return 签名
     */
    private String generateSign(TreeMap<String, Object> parameterMap) {
        return StringUtils.upperCase(DigestUtils.md5Hex(joinKeyValue(parameterMap, null, "&key=" + getApiKey(), "&", true)));
    }

}